package com.google.jessewilson.codesearch.util;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Model the progress of a particular subject, such as a download.
 *
 * @author jessewilson
 */
public class Progress {

  private List<Listener> listeners = new ArrayList<Listener>();
  private List<Task> tasks = new ArrayList<Task>();

  /**
   * Whether the task is currently working.
   */
  public synchronized boolean isBusy() {
    return !tasks.isEmpty();
  }

  /**
   * Add a new working task.
   */
  public synchronized Task startTask() {
    Task task = new Task();
    tasks.add(task);
    notifyListeners();
    return task;
  }

  private void notifyListeners() {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        for (Listener listener : listeners) {
          listener.progressUpdated(Progress.this);
        }
      }
    });
  }

  /**
   * An individual work effort.
   */
  public class Task {
    private Task() {
      // do nothing
    }

    /**
     * Mark this task as finished.
     */
    public void finished() {
      synchronized(Progress.this) {
        tasks.remove(this);
        notifyListeners();
      }
    }
  }

  /**
   * Listen for changes to this progress object.
   */
  public void addListener(Listener listener) {
    this.listeners.add(listener);
  }
  public void removeListener(Listener listener) {
    boolean removed = MoreCollections.removeByIdentity(listeners, listener);
    if (!removed) {
      throw new IllegalStateException("No such listener " + listener);
    }
  }

  public interface Listener {
    void progressUpdated(Progress progress);
  }
}
